package edu.nf.postlikework.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import edu.nf.postlikework.common.config.RabbitConfig;
import edu.nf.postlikework.common.confirm.ConfirmCallbackService;
import edu.nf.postlikework.common.confirm.RabbitManager;
import edu.nf.postlikework.common.enumeration.RedisKeyEnum;
import edu.nf.postlikework.mapper.LikeMapper;
import edu.nf.postlikework.model.dto.LikeDTO;
import edu.nf.postlikework.model.entity.Like;
import edu.nf.postlikework.service.LikeService;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author zjl
 * @date 2025/10/13
 */
@Service
@RequiredArgsConstructor
public class LikeServiceImpl implements LikeService, ConfirmCallbackService {
    private final LikeMapper  likeMapper;
    private final RedisTemplate <String,Integer> redisTemplate;
    /**
     * 注入封装的RabbitManager
     */
    private final RabbitManager<LikeDTO> rabbitManager;
    @Override
    public Boolean isLike(Integer postId, Integer userId) {
        synchronized (this) {
            //如果缓存中没有，那么从数据库点赞表中拉取当前帖子的点赞用户并缓存
            if (!redisTemplate.hasKey(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId)) {
                List<Like> list = likeMapper.listLikeByPostId(postId);
                list.forEach(like -> {
                    redisTemplate.opsForSet().add(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, like.getUserId());
                    //方式一：设置过期时间，72小时
                    //redisTemplate.expire(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, Duration.ofHours(72));
                    //方式二：设置过期时间,6000秒
                    redisTemplate.expire(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, 6000, TimeUnit.SECONDS);
                });
            }
        }
        // 判断当前用户是否点过赞(是否存在于 Redis的Set中)
        return redisTemplate.opsForSet().isMember(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
    }

    @Override
    public LikeDTO like(Integer postId, Integer userId) {
        boolean likeStatus = false;
        //如果已经点赞过
        if (isLike(postId,userId)){
            //将用户ID从set集合中移除
            redisTemplate.opsForSet().remove(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
        }else{
            likeStatus = true;
            //将用户ID加到set集合中
            redisTemplate.opsForSet().add(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
        }
        // 获取当前帖子在redis中的点赞总数
        Long likeCount = redisTemplate.opsForSet().size(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId);
        //创建LikeDTO封装修改的数据并发布到消息队列
        LikeDTO likeDTO = new LikeDTO(postId,userId,likeStatus,likeCount);
        //发送到mq异步更新到数据库
        rabbitManager.send(RabbitConfig.EXCHANGE_NAME,RabbitConfig.ROUTER_KEY,"likeServiceImpl",likeDTO);
        return likeDTO;
    }

    /**
     * 执行失败后的反向操作
     * @param message 投递的消息对象
     */
    @Override
    public void confirmCallback(Message message) {
        byte[] bytes = message.getBody();
        try {
            //反序列化为LikeDTO对象
            LikeDTO dto = new ObjectMapper().readValue(bytes,LikeDTO.class);
            if (dto.getLikeStatus()){
                redisTemplate.opsForSet().add(RedisKeyEnum.POST_LIKE_PREFIX.getValue()+dto.getPostId(),dto.getUserId());
            }else{
                redisTemplate.opsForSet().remove(RedisKeyEnum.POST_LIKE_PREFIX.getValue()+dto.getPostId());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
